home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_055 / csh / execom.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  18KB  |  694 lines

  1. /*
  2.  * EXECOM.C
  3.  *
  4.  * Matthew Dillon, 10 August 1986
  5.  *    Finally re-written.
  6.  *
  7.  * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
  8.  *
  9.  *
  10.  */
  11.  
  12. #include "shell.h"
  13.  
  14. #define F_EXACT 0
  15. #define F_ABBR  1
  16.  
  17. #define ST_COND   0x03
  18. #define ST_NAME   0x02
  19.  
  20. int has_wild = 0;                 /* set if any arg has wild card */
  21.  
  22. struct _dev     {
  23.         long  fd;
  24.         short mode;
  25.     };
  26.  
  27. struct COMMAND {
  28.    int (*func)();
  29.    short minargs;
  30.    short stat;
  31.    int   val;
  32.    char *name;
  33. };
  34.  
  35. extern char *format_insert_string();
  36. extern char *mpush(), *exarg();
  37.  
  38. extern int do_run(), do_number();
  39. extern int do_quit(), do_set_var(), do_unset_var();
  40. extern int do_echo(), do_source(), do_mv();
  41. extern int do_cd(), do_rm(), do_mkdir(), do_history();
  42. extern int do_mem(), do_cat(), do_dir(), do_inc();
  43. extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
  44. extern int do_input(), do_ver(), do_sleep(), do_help();
  45. extern int do_strhead(), do_strtail();
  46. extern int do_copy(), date(),  do_ps();
  47. extern int do_forever(), do_abortline();
  48.  
  49. static struct COMMAND Command[] = {
  50.    do_run      , 0,  0,         0 ,   "\001",
  51.    do_number   , 0,  0,          0 ,   "\001",
  52.    do_set_var  , 0,  0, LEVEL_ALIAS,   "alias",
  53.    do_abortline, 0,  0,          0,    "abortline",   
  54.    do_cd       , 0,  0,          0 ,   "cd",
  55.    do_cat      , 0,  0,          0 ,   "cat",
  56.    do_copy     , 1,  0,          0 ,   "copy",
  57.    date        , 0,  0,          0 ,   "date",
  58.    do_dir      , 0,  0,          0 ,   "dir",
  59.    do_inc      , 1,  0,         -1 ,   "dec",
  60.    do_dir      , 0,  0,         -1 ,   "devinfo",
  61.    do_echo     , 0,  0,          0 ,   "echo",
  62.    do_if       , 0,  ST_COND,    1 ,   "else",
  63.    do_if       , 0,  ST_COND,    2 ,   "endif",
  64.    do_foreach  , 3,  0,          0 ,   "foreach",
  65.    do_forever  , 1,  0,          0 ,   "forever",   
  66.    do_goto     , 1,  0,          0 ,   "goto",
  67.    do_help     , 0,  0,          0 ,   "help",
  68.    do_history  , 0,  0,          0 ,   "history",
  69.    do_if       , 1,  ST_COND,    0 ,   "if",
  70.    do_inc      , 1,  0,          1 ,   "inc",
  71.    do_input    , 1,  0,          0 ,   "input",
  72.    do_label    , 1,  ST_COND,    0 ,   "label",
  73.    do_mem      , 0,  0,          0 ,   "mem",
  74.    do_mkdir    , 0,  0,          0 ,   "mkdir",
  75.    do_mv       , 2,  0,          0 ,   "mv",   
  76.    do_ps       , 0,  0,          0,    "ps",
  77.    do_cd       , 0,  0,         -1 ,   "pwd",
  78.    do_quit     , 0,  0,          0 ,   "quit",
  79.    do_return   , 0,  0,          0 ,   "return",
  80.    do_rm       , 0,  0,          0 ,   "rm",
  81.    do_run      , 1,  ST_NAME,    0 ,   "run",
  82.    do_set_var  , 0,  0, LEVEL_SET  ,   "set",
  83.    do_sleep    , 0,  0,          0,    "sleep",
  84.    do_source   , 0,  0,          0 ,   "source",
  85.    do_strhead  , 3,  0,          0 ,   "strhead",
  86.    do_strtail  , 3,  0,          0 ,   "strtail",
  87.    do_unset_var, 0,  0, LEVEL_ALIAS,   "unalias",
  88.    do_unset_var, 0,  0, LEVEL_SET  ,   "unset",
  89.    do_ver      , 0,  0,          0 ,   "version",
  90.    '\0'        , 0,  0,          0 ,   NULL
  91. };
  92.  
  93.   
  94. static unsigned char elast;          /* last end delimeter */
  95. static char Cin_ispipe, Cout_ispipe;
  96.  
  97. exec_command(base)
  98. char *base;
  99. {
  100.    register char *scr;
  101.    register int i;
  102.    char buf[32];
  103.  
  104.    if (!H_stack) {
  105.       add_history(base);
  106.       sprintf(buf, "%d", H_tail_base + H_len);
  107.       set_var(LEVEL_SET, V_HISTNUM, buf);
  108.    }
  109.    scr = malloc((strlen(base) << 2) + 2);    /* 4X */
  110.    preformat(base, scr);
  111.    i = fcomm(scr, 1);
  112.    return ((i) ? -1 : 1);
  113. }
  114.  
  115. isalphanum(c)
  116. char c;
  117. {
  118.    if (c >= '0' && c <= '9')
  119.       return (1);
  120.    if (c >= 'a' && c <= 'z')
  121.       return (1);
  122.    if (c >= 'A' && c <= 'Z')
  123.       return (1);
  124.    if (c == '_')
  125.       return (1);
  126.    return (0);
  127. }
  128.  
  129. preformat(s, d)
  130. register char *s, *d;
  131. {
  132.    register int si, di, qm;
  133.  
  134.    si = di = qm = 0;
  135.    while (s[si] == ' ' || s[si] == 9)
  136.       ++si;
  137.    while (s[si]) {
  138.       if (qm && s[si] != '\"' && s[si] != '\\') {
  139.          d[di++] = s[si++] | 0x80;
  140.          continue;
  141.       }
  142.       switch (s[si]) {
  143.       case ' ':
  144.       case 9:
  145.          d[di++] = ' ';
  146.          while (s[si] == ' ' || s[si] == 9)
  147.             ++si;
  148.          if (s[si] == 0 || s[si] == '|' || s[si] == ';')
  149.             --di;
  150.          break;
  151.       case '*':
  152.       case '?':
  153.          d[di++] = 0x80;
  154.       case '!':
  155.          d[di++] = s[si++];
  156.          break;
  157.       case '#':
  158.          d[di++] = '\0';
  159.          while (s[si])
  160.             ++si;
  161.          break;
  162.       case ';':
  163.       case '|':
  164.          d[di++] = s[si++];
  165.          while (s[si] == ' ' || s[si] == 9)
  166.             ++si;
  167.          break;
  168.       case '\\':
  169.          d[di++] = s[++si] | 0x80;
  170.          if (s[si]) ++si;
  171.          break;
  172.       case '\"':
  173.          qm = 1 - qm;
  174.          ++si;
  175.          break;
  176.       case '^':
  177.          d[di++] = s[++si] & 0x1F;
  178.          if (s[si]) ++si;
  179.          break;
  180.       case '$':         /* search end of var name and place false space */
  181.          d[di++] = 0x80;
  182.          d[di++] = s[si++];
  183.          while (isalphanum(s[si]))
  184.             d[di++] = s[si++];
  185.          d[di++] = 0x80;
  186.          break;
  187.       default:
  188.          d[di++] = s[si++];
  189.          break;
  190.       }
  191.    }
  192.    d[di++] = 0;
  193.    d[di]   = 0;
  194.    if (debug & 0x01) {
  195.       fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
  196.    }
  197. }
  198.  
  199. /*
  200.  * process formatted string.  ' ' is the delimeter.
  201.  *
  202.  *    0: check '\0': no more, stop, done.
  203.  *    1: check $.     if so, extract, format, insert
  204.  *    2: check alias. if so, extract, format, insert. goto 1
  205.  *    3: check history or substitution, extract, format, insert. goto 1
  206.  *
  207.  *    4: assume first element now internal or disk based command.
  208.  *
  209.  *    5: extract each ' ' or 0x80 delimited argument and process, placing
  210.  *       in av[] list (except 0x80 args appended).  check in order:
  211.  *
  212.  *             '$'         insert string straight
  213.  *             '>'         setup stdout
  214.  *             '>>'        setup stdout flag for append
  215.  *             '<'         setup stdin
  216.  *             '*' or '?'  do directory search and insert as separate args.
  217.  *
  218.  *             ';' 0 '|'   end of command.  if '|' setup stdout
  219.  *                          -execute command, fix stdin and out (|) sets
  220.  *                           up stdin for next guy.
  221.  */
  222.  
  223.  
  224. fcomm(str, freeok)
  225. register char *str;
  226. {
  227.    static int alias_count;
  228.    int p_alias_count = 0;
  229.    char *istr;
  230.    char *nextstr;
  231.    char *command;
  232.    char *pend_alias = NULL;
  233.    char err = 0;
  234.    has_wild = 0;
  235.    ++alias_count;
  236.    
  237.    mpush_base();
  238.    if (*str == 0)
  239.       goto done1;
  240. step1:
  241.    if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) {
  242.       fprintf(stderr,"Alias Loop\n");
  243.       err = 20;
  244.       goto done1;
  245.    }
  246.    if (*str == '$') {
  247.       if (istr = get_var (LEVEL_SET, str + 1))
  248.          str = format_insert_string(str, istr, &freeok);
  249.    }
  250.    istr = NULL;
  251.    if (*(unsigned char *)str < 0x80)
  252.       istr = get_var (LEVEL_ALIAS, str);  /* only if not \command */
  253.    *str &= 0x7F;                          /* remove \ teltail     */
  254.    if (istr) {
  255.       if (*istr == '%') {
  256.          pend_alias = istr;
  257.       } else {
  258.          str = format_insert_string(str, istr, &freeok);
  259.          goto step1;
  260.       }
  261.    }
  262.    if (*str == '!') {
  263.       char *p, c;              /* fix to allow !cmd1;!cmd2 */
  264.       for(p = str; *p && *p != ';' ; ++p);
  265.       c = *p;
  266.       *p = '\0';      
  267.       istr = get_history(str);
  268.       *p = c;
  269.       replace_head(istr);        
  270.       str = format_insert_string(str, istr, &freeok);
  271.       goto step1;
  272.    }
  273.    nextstr = str;
  274.    command = exarg(&nextstr);
  275.    if (*command == 0)
  276.       goto done0;
  277.    if (pend_alias == 0) {
  278.       register int ccno;
  279.       ccno = find_command(command);
  280.       if (Command[ccno].stat & ST_COND)
  281.          goto skipgood;
  282.    }
  283.    if (disable) {
  284.       while (elast && elast != ';' && elast != '|')
  285.          exarg(&nextstr);
  286.       goto done0;
  287.    }
  288. skipgood:
  289.    {
  290.       register char *arg, *ptr, *scr;
  291.       short redir;
  292.       short doexpand;
  293.       short cont;
  294.       short inc;
  295.  
  296.       ac = 1;
  297.       av[0] = command;
  298. step5:                                          /* ac = nextac */
  299.       if (!elast || elast == ';' || elast == '|')
  300.          goto stepdone;
  301.  
  302.       av[ac] = '\0';
  303.       cont = 1;
  304.       doexpand = redir = inc = 0;
  305.  
  306.       while (cont && elast) {
  307.          ptr = exarg(&nextstr);
  308.          inc = 1;
  309.          arg = "";
  310.          cont = (elast == 0x80);
  311.          switch (*ptr) {
  312.          case '<':
  313.             redir = -2;
  314.          case '>':
  315.             if ((Command[find_command(command)].stat & ST_NAME) != 0) { 
  316.                                     /* don't extract   */
  317.                 redir = 0;                /* <> stuff if its */
  318.                 arg = ptr;                /* external cmd.   */
  319.                 break;    
  320.             }
  321.             ++redir;
  322.             arg = ptr + 1;
  323.             if (*arg == '>') {
  324.                redir = 2;        /* append >> (not impl yet) */
  325.                ++arg;
  326.             }            
  327.             cont = 1;
  328.             break;
  329.          case '$':
  330.             if ((arg = get_var(LEVEL_SET, ptr + 1)) == NULL)
  331.                arg = ptr;
  332.             break;
  333.          case '*':
  334.          case '?':
  335.             doexpand = 1;
  336.             arg = ptr;
  337.             break;
  338.          default:
  339.             arg = ptr;
  340.             break;
  341.          }
  342.  
  343.          /* Append arg to av[ac] */
  344.  
  345.          for (scr = arg; *scr; ++scr)
  346.             *scr &= 0x7F;
  347.          if (av[ac]) {
  348.             register char *old = av[ac];
  349.             av[ac] = mpush(strlen(arg)+1+strlen(av[ac]));
  350.             strcpy(av[ac], old);
  351.             strcat(av[ac], arg);
  352.          } else {
  353.             av[ac] = mpush(strlen(arg)+1);
  354.             strcpy(av[ac], arg);
  355.          }
  356.          if (elast != 0x80)
  357.             break;
  358.       }
  359.  
  360.       /* process expansion */
  361.  
  362.       if (doexpand) {
  363.          char **eav, **ebase;
  364.          int eac;
  365.       has_wild = 1;
  366.          eav = ebase = expand(av[ac], &eac);
  367.          inc = 0;
  368.          if (eav) {
  369.             if (ac + eac + 2 > MAXAV) {
  370.                ierror (NULL, 506);
  371.                err = 1;
  372.             } else {               
  373.                QuickSort(eav, eac);
  374.                for (; eac; --eac, ++eav)
  375.                   av[ac++] = strcpy(mpush(strlen(*eav)+1), *eav);
  376.             }
  377.             free_expand (ebase);
  378.          }
  379.       }
  380.  
  381.       /* process redirection  */
  382.  
  383.       if (redir && !err) {
  384.          register char *file = (doexpand) ? av[--ac] : av[ac];
  385.  
  386.          if (redir < 0)
  387.             Cin_name = file;
  388.          else {             
  389.             Cout_name = file;
  390.             Cout_append = (redir == 2);
  391.          }            
  392.          inc = 0;
  393.       }
  394.  
  395.       /* check elast for space */
  396.  
  397.       if (inc) {
  398.          ++ac;
  399.          if (ac + 2 > MAXAV) {
  400.             ierror (NULL, 506);
  401.             err = 1;                /* error condition */
  402.             elast = 0;              /* don't process any more arguemnts */
  403.          }
  404.       }
  405.       if (elast == ' ')
  406.          goto step5;
  407.    }
  408. stepdone:
  409.    av[ac] = '\0';
  410.  
  411.    /* process pipes via files */
  412.  
  413.    if (elast == '|' && !err) {
  414.       static int which;             /* 0 or 1 in case of multiple pipes */
  415.       which = 1 - which;
  416.       Cout_name = (which) ? Pipe1 : Pipe2;
  417.       Cout_ispipe = 1;
  418.    }
  419.  
  420.  
  421.    if (err)
  422.       goto done0;
  423.  
  424.    {
  425.       register int i, len;
  426.       char save_elast;
  427.       register char *avline;
  428.  
  429.       save_elast = elast;
  430.       for (i = len = 0; i < ac; ++i)
  431.          len += strlen(av[i]) + 1;
  432.       avline = malloc(len+1);
  433.       for (len = 0, i = ((pend_alias) ? 1 : 0); i < ac; ++i) {
  434.          if (debug & 0x02) { 
  435.              fprintf (stderr, "AV[%2d] %d :%s:\n", i, strlen(av[i]), av[i]);
  436.          }
  437.          strcpy(avline + len, av[i]);
  438.          len += strlen(av[i]);
  439.          if (i + 1 < ac)
  440.             avline[len++] = ' ';
  441.       }
  442.       avline[len] = 0;
  443.       if (pend_alias) {                               /* special % alias */
  444.          register char *ptr, *scr;
  445.          for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
  446.          set_var (LEVEL_SET, pend_alias + 1, avline);
  447.          free (avline);
  448.  
  449.          scr = malloc((strlen(ptr) << 2) + 2);
  450.          preformat (ptr, scr);
  451.          fcomm (scr, 1);
  452.          unset_var (LEVEL_SET, pend_alias + 1);
  453.       } else {                                        /* normal command  */
  454.          register int ccno;
  455.          long  oldcin = (long)Input();
  456.       long  oldcout = (long)Output();
  457.      extern struct _dev _devtab[];
  458.      struct _dev *stdfp;
  459.      
  460.      fflush(stdout);
  461.          ccno = find_command (command);
  462.          if ((Command[ccno].stat & ST_NAME) == 0) {
  463.             if (Cin_name) {
  464.                if ((Cin = (long)Open(Cin_name,1005L)) == 0L) {
  465.                   ierror (NULL, 504);
  466.                   err = 1;
  467.                   Cin_name = '\0';
  468.                } else {
  469.                   Myprocess->pr_CIS = Cin;
  470.                _devtab[stdin->_unit].fd = Cin;
  471.                }
  472.             }
  473.             if (Cout_name) {               
  474.                if (Cout_append) {
  475.                   if ((Cout = (long)Open(Cout_name, 1005L)) != 0L)
  476.                      Seek(Cout, 0L, 1L);
  477.                } else {
  478.                   Cout = (long)Open(Cout_name,1006L);
  479.            }
  480.                if (Cout == NULL) {
  481.                   err = 1;
  482.                   ierror (NULL, 504);
  483.                   Cout_name = '\0';
  484.                   Cout_append = 0;
  485.                } else {
  486.                   Myprocess->pr_COS = Cout;
  487.                   _devtab[stdout->_unit].fd = Cout;
  488.                }
  489.             }
  490.          }
  491.          if (ac < Command[ccno].minargs + 1) {
  492.             ierror (NULL, 500);
  493.             err = -1;
  494.          } else if (!err) {
  495.             i = (*Command[ccno].func)(avline, Command[ccno].val);
  496.             if (i < 0)
  497.                i = 20;
  498.             err = i;
  499.          }
  500.          free (avline);
  501.          if (Exec_ignoreresult == 0 && Lastresult != err) {
  502.             Lastresult = err;
  503.             seterr();
  504.          }
  505.          if ((Command[ccno].stat & ST_NAME) == 0) {
  506.             if (Cin_name) {
  507.                fflush(stdin); 
  508.            clearerr(stdin);
  509.            Close(Cin);
  510.             }
  511.             if (Cout_name) {
  512.                fflush(stdout);
  513.                clearerr(stdout);
  514.                stdout->_flags &= ~_DIRTY;    /* because of nil: device */
  515.                Close(Cout);
  516.                Cout_append = 0;
  517.             }
  518.          }
  519.  
  520.         /* the next few lines solve a bug with fexecv and bcpl programs */
  521.         /* that muck up the input/output streams  which causes GURUs    */
  522.  
  523.          Myprocess->pr_CIS =  _devtab[stdin->_unit].fd = oldcin;
  524.          Myprocess->pr_COS =  _devtab[stdout->_unit].fd = oldcout;       
  525.       }
  526.       if (Cin_ispipe && Cin_name)
  527.          DeleteFile(Cin_name);
  528.       if (Cout_ispipe) {
  529.          Cin_name = Cout_name;         /* ok to assign.. static name */
  530.          Cin_ispipe = 1;
  531.       } else {
  532.          Cin_name = '\0';
  533.       }
  534.       Cout_name = '\0';
  535.       Cout_ispipe = 0;
  536.       elast = save_elast;
  537.    }
  538.    mpop_tobase();                      /* free arguments   */
  539.    mpush_base();                       /* push dummy base  */
  540.  
  541. done0:
  542.    {
  543.       char *str;
  544.       if (err && E_stack == 0) {
  545.          str = get_var(LEVEL_SET, V_EXCEPT);
  546.          if (err >= ((str)?atoi(str):1)) {
  547.             if (str) {
  548.                ++H_stack;
  549.                ++E_stack;
  550.                exec_command(str);
  551.                --E_stack;
  552.                --H_stack;
  553.             } else {
  554.                Exec_abortline = 1;
  555.             }
  556.          }
  557.       }
  558.       if (elast != 0 && Exec_abortline == 0)
  559.          err = fcomm(nextstr, 0);
  560.       Exec_abortline = 0;
  561.       if (Cin_name)
  562.          DeleteFile(Cin_name);
  563.       Cin_name = NULL;
  564.       Cin_ispipe = 0;
  565.    } 
  566. done1:
  567.    mpop_tobase();
  568.    if (freeok)
  569.       free(str);
  570.    --alias_count;
  571.    return ((int)err);                  /* TRUE = error occured    */
  572. }
  573.  
  574.  
  575. char *
  576. exarg(ptr)
  577. unsigned char **ptr;
  578. {
  579.    register unsigned char *end;
  580.    register unsigned char *start;
  581.  
  582.    start = end = *ptr;
  583.    while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
  584.       ++end;
  585.    elast = *end;
  586.    *end = '\0';
  587.    *ptr = end + 1;
  588.    return ((char *)start);
  589. }
  590.  
  591. static char **Mlist;
  592.  
  593. mpush_base()
  594. {
  595.    char *str;
  596.  
  597.    str = malloc(5);
  598.    *(char ***)str = Mlist;
  599.    str[4] = 0;
  600.    Mlist = (char **)str;
  601. }
  602.  
  603. char *
  604. mpush(bytes)
  605. {
  606.    char *str;
  607.  
  608.    str = malloc(5 + bytes);
  609.    *(char ***)str = Mlist;
  610.    str[4] = 1;
  611.    Mlist = (char **)str;
  612.    return (str + 5);
  613. }
  614.  
  615. mpop_tobase()
  616. {
  617.    register char *next;
  618.    while (Mlist) {
  619.       next = *Mlist;
  620.       if (((char *)Mlist)[4] == 0) {
  621.          free (Mlist);
  622.          Mlist = (char **)next;
  623.          break;
  624.       }
  625.       free (Mlist);
  626.       Mlist = (char **)next;
  627.    }
  628. }
  629.  
  630.  
  631. /*
  632.  * Insert 'from' string in front of 'str' while deleting the
  633.  * first entry in 'str'.  if freeok is set, then 'str' will be
  634.  * free'd
  635.  */
  636.  
  637.  
  638.  
  639. char *
  640. format_insert_string(str, from, freeok)
  641. char *str;
  642. char *from;
  643. int *freeok;
  644. {
  645.    register char *new1, *new2;
  646.    register unsigned char *strskip;
  647.    int len;
  648.  
  649.    for (strskip = (unsigned char *)str; *strskip && *strskip != ' ' && *strskip != ';' && *strskip != '|' && *strskip != 0x80; ++strskip);
  650.    len = strlen(from);
  651.    new1 = malloc((len << 2) + 2);
  652.    preformat(from, new1);
  653.    len = strlen(new1) + strlen(strskip);
  654.    new2 = malloc(len+2);
  655.    strcpy(new2, new1);
  656.    strcat(new2, strskip);
  657.    new2[len+1] = 0;
  658.    free (new1);
  659.    if (*freeok)
  660.       free (str);
  661.    *freeok = 1;
  662.    return (new2);
  663. }
  664.  
  665. find_command(str)
  666. char *str;
  667. {
  668.    int i;
  669.    int len = strlen(str);
  670.  
  671.    if (*str >= '0'  &&  *str <= '9')
  672.       return (1);
  673.    for (i = 0; Command[i].func; ++i) {
  674.       if (strncmp (str, Command[i].name, len) == 0)
  675.          return (i);
  676.    }
  677.    return (0);
  678. }
  679.  
  680. do_help()
  681. {
  682.    register struct COMMAND *com;
  683.    int i= 0;
  684.  
  685.     
  686.    for (com = &Command[2]; com->func; ++com) {
  687.       printf ("%-12s", com->name);
  688.       if (++i  % 6 == 0) printf("\n");
  689.    }
  690.    printf("\n");
  691.    return(0);
  692. }
  693.  
  694.